#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMenuBar>
#include <QApplication>
#include <QScreen>
#include <QToolBar>
#include <QLabel>
#include <QDebug>
#include <QFile>
#include <QCloseEvent>
#include <QFileDialog>
#include <QClipboard>
#include <QDateTime>
#include <QMessageBox>
#include <QTextBlock>
#include <QFontDialog>
#include <QDesktopServices>
#include "./LogTool/easylogging++.h"
#include <QDir>
#include <genericdialog.h>
#include <memory> // 包含智能指针头文件

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    textEdit = new QTextEdit(this);
    //设置窗口中心部件
    setCentralWidget(textEdit);
    initial();
    createMenuBar();
    createStatusBar();
    statusBar()->showMessage("文本已就绪");

    connect(textEdit, &QTextEdit::selectionChanged, this, &MainWindow::updateActionEnable);

    QClipboard *clipboard = QApplication::clipboard();
    connect(clipboard,&QClipboard::dataChanged,this,&MainWindow::updatePasteActionEnable);

    connect(textEdit,&QTextEdit::textChanged,this,&MainWindow::checkInputTextEmpty);

    connect(textEdit,&QTextEdit::cursorPositionChanged,this,&MainWindow::updateCursorPos);
    connect(textEdit->document(),&QTextDocument::contentsChanged,this,&MainWindow::updateCursorPos);
}

MainWindow::~MainWindow()
{
    delete ui;
}

/***************************************************************
* @function name: initial()
* @摘要:进行初始化工作
* @作用:设置窗口标题、图标。将窗口移植屏幕中央，初始化指针置为空
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::initial()
{
    this->setWindowTitle(tr("HanL的记事本"));
    this->setWindowIcon(QIcon(":/image/windowICon.png"));

    textEdit->setFontWeight(12);

    QRect screen = QApplication::primaryScreen()->geometry();
    move((screen.width()-this->width())/2,(screen.height()-this->height())/2);

    fileMenu = nullptr;
    editMenu = nullptr;
    formatMenu = nullptr;
    viewMenu = nullptr;
    subScaleMenu = nullptr;
    helpMenu = nullptr;
    /*edit Action*/
    revokeAction = nullptr;
    cutAction = nullptr;
    copyAction = nullptr;
    pasteAction = nullptr;
    deleteAction = nullptr;
    bingSearchAction = nullptr;
    searchAction = nullptr;
    searchPreAction = nullptr;
    searchNextAction = nullptr;

    m_findDialog = nullptr;
    m_replaceDialog = nullptr;
    isFound = false;
    m_gotoRowDialog = nullptr;

    autoWrapAction = nullptr;
    zoom = nullptr;
    rowLabel = nullptr;
}

/***************************************************************
* @function name: createMenuBar()
* @摘要:创建菜单栏
* @作用:创建各种文件、编辑、格式、查看、帮助等菜单
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::createMenuBar()
{
    QMenuBar* bar = menuBar();
    setMenuBar(bar);

    fileMenu = bar->addMenu(tr("文件(F)"));
    createFileMenu();

    editMenu = bar->addMenu(tr("编辑(E)"));
    createEditMenu();

    formatMenu = bar->addMenu(tr("格式(O)"));
    createformatMenu();

    viewMenu = bar->addMenu(tr("查看(Y)"));
    subScaleMenu = viewMenu->addMenu(tr("缩放(Z)"));
    createScaleMenu();
    createViewMenu();

    helpMenu = bar->addMenu(tr("帮助(H)"));
    createHelpMenu();
}

/***************************************************************
* @function name: createFileMenu()
* @摘要:创建文件菜单
* @作用:为每个QAction设置状态栏提示、设置快捷键、绑定信号与槽
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::createFileMenu()
{
    QAction *newAction = new QAction(tr("新建(N)\tCtrl+N"),this);
    newAction->setStatusTip(tr("创建一个新文件"));
    //newAction->setShortcut(QKeySequence(tr("Ctrl+N")));
    newAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N));
    fileMenu->addAction(newAction);
    connect(newAction,&QAction::triggered,this,&MainWindow::createNewFile);

    QAction* newWinAction = new QAction(tr("新窗口(W)\tCtrl+Shift+N"),this);
    fileMenu->addAction(newWinAction);
    newWinAction->setShortcut(QKeySequence(tr("Ctrl+Shift+N")));
    newWinAction->setStatusTip(tr("创建一个新窗口"));
    connect(newWinAction,&QAction::triggered,this,&MainWindow::openNewWin);

    QAction* openAction = new QAction(tr("打开(O)\tCtrl+O"),this);
    fileMenu->addAction(openAction);
    openAction->setStatusTip(tr("打开一个.txt文件"));
    openAction->setShortcut(QKeySequence(tr("Ctrl+O")));
    connect(openAction,&QAction::triggered,this,&MainWindow::openFile);

    QAction* saveAction = new QAction(tr("保存(S)\tCtrl+S"),this);
    saveAction->setShortcut(QKeySequence(tr("Ctrl+S")));
    saveAction->setStatusTip(tr("保存当前编辑内容"));
    connect(saveAction,&QAction::triggered,this,&MainWindow::saveFile);
    fileMenu->addAction(saveAction);

    QAction* saveAsAction = new QAction(tr("另存为(A)\tCtrl+Shift+S"),this);
    fileMenu->addAction(saveAsAction);
    saveAsAction->setStatusTip(tr("将当前编辑内容另存为"));
    saveAsAction->setShortcut(QKeySequence(tr("Ctrl+Shift+S")));
    connect(saveAsAction,&QAction::triggered,this,&MainWindow::saveAsFile);

    fileMenu->addSeparator();

    QAction* pageSetAction = new QAction(tr("页面设置(U)"),this);
    fileMenu->addAction(pageSetAction);
    pageSetAction->setStatusTip(tr("该功能暂未考虑实现"));

    QAction* printAction = new QAction(tr("打印(P)\tCtrl+P"),this);
    fileMenu->addAction(printAction);
    printAction->setStatusTip(tr("该功能暂未考虑实现"));

    fileMenu->addSeparator();

    QAction* exitAction = new QAction(tr("退出(X)"),this);
    fileMenu->addAction(exitAction);
    exitAction->setShortcut(QKeySequence(tr("X")));
    exitAction->setStatusTip(tr("退出HanL的记事本"));
    connect(exitAction,&QAction::triggered,this,&MainWindow::closeApp);
}

/***************************************************************
* @function name: createEditMenu()
* @摘要:创建编辑菜单
* @作用:为每个QAction设置状态栏提示、设置快捷键、绑定信号与槽等
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::createEditMenu()
{
    revokeAction = new QAction(tr("撤销(U)\tCtrl+Z"),this);
    editMenu->addAction(revokeAction);
    revokeAction->setShortcut(QKeySequence(tr("Ctrl+Z")));
    connect(revokeAction,&QAction::triggered,this,&MainWindow::undo);
    revokeAction->setToolTip(tr("撤销上一步的操作"));

    editMenu->addSeparator();

    cutAction = new QAction(tr("剪切(X)\tCtrl+X"),this);
    editMenu->addAction(cutAction);
    cutAction->setShortcut(QKeySequence(tr("Ctrl+X")));
    connect(cutAction,&QAction::triggered,this,&MainWindow::cut);
    cutAction->setEnabled(false);
    cutAction->setToolTip(tr("剪切选中的文本到剪贴板"));

    copyAction = new QAction(tr("复制(C)\tCtrl+C"),this);
    editMenu->addAction(copyAction);
    copyAction->setShortcut(QKeySequence(tr("Ctrl+C")));
    connect(copyAction,&QAction::triggered,this,&MainWindow::copy);
    copyAction->setEnabled(false);
    copyAction->setToolTip(tr("复制文本到剪贴板"));

    pasteAction = new QAction(tr("粘贴(V)\tCtrl+V"),this);
    editMenu->addAction(pasteAction);
    pasteAction->setShortcut(QKeySequence(tr("Ctrl+V")));
    connect(pasteAction,&QAction::triggered,this,&MainWindow::paste);
    pasteAction->setToolTip(tr("粘贴剪切板中的文本"));


    deleteAction = new QAction(tr("删除(L)\tDel"),this);
    editMenu->addAction(deleteAction);
    pasteAction->setShortcut(QKeySequence(tr("Del")));
    connect(deleteAction,&QAction::triggered,this,&MainWindow::deleteSelect);
    deleteAction->setEnabled(false);
    deleteAction->setToolTip(tr("删除选中文本"));



    editMenu->addSeparator();

    bingSearchAction = new QAction(tr("使用Bing搜索\tCtrl+E"),this);
    editMenu->addAction(bingSearchAction);
    bingSearchAction->setEnabled(false);

    searchAction = new QAction(tr("查找(F)\tCtrl+F"),this);
    editMenu->addAction(searchAction);
    searchAction->setStatusTip(tr("查看编辑内容"));
    searchAction->setShortcut(QKeySequence(tr("Ctrl+F")));
    searchAction->setEnabled(false);
    connect(searchAction,&QAction::triggered,this,&MainWindow::search);

    searchPreAction = new QAction(tr("查找上一个\t(V)"),this);
    editMenu->addAction(searchPreAction);
    searchPreAction->setEnabled(false);
    connect(searchPreAction,&QAction::triggered,this,[=](){
        if(!m_findDialog)
        {
            search();
        }else
        {
            searchMatchText(tempSearchStr,false,false,true);
        }

    });


    searchNextAction = new QAction(tr("查找下一个\t(V)"),this);
    editMenu->addAction(searchNextAction);
    searchNextAction->setEnabled(false);
    connect(searchNextAction,&QAction::triggered,this,[=](){
        if(!m_findDialog)
        {
            search();
        }else
        {
            searchMatchText(tempSearchStr,false,false,false);
        }

    });

    QAction* replaceAction = new QAction(tr("替换(R)\tCtrl+H"),this);
    editMenu->addAction(replaceAction);
    replaceAction->setStatusTip(tr("替换编辑文本"));
    replaceAction->setShortcut(QKeySequence(tr("Ctrl+H")));
    connect(replaceAction,&QAction::triggered,this,&MainWindow::replace);

    QAction* turnToAction = new QAction(tr("转到(G)\tCtrl+G"),this);
    editMenu->addAction(turnToAction);
    turnToAction->setStatusTip(tr("转到对应的行"));
    turnToAction->setShortcut(QKeySequence(tr("Ctrl+G")));
    connect(turnToAction,&QAction::triggered,this,&MainWindow::goToRow);

    editMenu->addSeparator();

    QAction *allSelectAction = new QAction(tr("全选(A)\tCtrl+A"));
    editMenu->addAction(allSelectAction);
    allSelectAction->setShortcut(QKeySequence(tr("Ctrl+A")));
    connect(allSelectAction,&QAction::triggered,this,&MainWindow::allSelect);
    allSelectAction->setToolTip(tr("选中所有文本"));

    QAction *timeAndDateAction = new QAction(tr("时间/日期(D)\tF5"));
    editMenu->addAction(timeAndDateAction);
    timeAndDateAction->setShortcut(QKeySequence(tr("F5")));
    connect(timeAndDateAction,&QAction::triggered,this,&MainWindow::inputTimeAndDate);
}
/***************************************************************
* @function name:createformatMenu()
* @摘要:创建格式菜单
* @作用:为每个QAction设置状态栏提示、设置快捷键、绑定信号与槽等
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::createformatMenu()
{
    autoWrapAction = new QAction(tr("自动换行(W)"),this);
    formatMenu->addAction(autoWrapAction);
    autoWrapAction->setCheckable(true);
    connect(autoWrapAction,&QAction::triggered,this,&MainWindow::isAutoWrap);

    QAction* fontAction = new QAction(tr("字体(F)"),this);
    formatMenu->addAction(fontAction);
    connect(fontAction,&QAction::triggered,this,&MainWindow::selectFont);
}
/***************************************************************
* @function name:createViewMenu()
* @摘要:创建查看菜单
* @作用:为每个QAction设置状态栏提示、绑定信号与槽等
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::createViewMenu()
{
    QAction* statusAction = new QAction(tr("状态栏(S)"),this);
    viewMenu->addAction(statusAction);
    statusAction->setStatusTip(tr("状态栏的显示或隐藏"));
    connect(statusAction,&QAction::triggered,this,&MainWindow::statusBarShow);
}
/***************************************************************
* @function name:createScaleMenu()
* @摘要:创建缩放菜单,
* @作用:该菜单下有放大、缩小、恢复默认缩放三个Action.与状态栏相同均属于查看菜单下
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::createScaleMenu()
{
    QAction * zoomAction = new QAction(tr("放大(I)\tCtrl + 加号"));
    subScaleMenu->addAction(zoomAction);
    zoomAction->setShortcut(QKeySequence::ZoomIn);
    connect(zoomAction,&QAction::triggered,this,&MainWindow::zoomIn);

    QAction * shrinkAction = new QAction(tr("缩小(O)\tCtrl + 减号"));
    shrinkAction->setShortcut(QKeySequence::ZoomOut);
    subScaleMenu->addAction(shrinkAction);
    connect(shrinkAction,&QAction::triggered,this,&MainWindow::zoomOut);

    QAction * recoverDefAction = new QAction(tr("恢复默认缩放\tCtrl+0"));
    subScaleMenu->addAction(recoverDefAction);
    recoverDefAction->setShortcut(QKeySequence("Ctrl+0"));
    connect(recoverDefAction,&QAction::triggered,this,&MainWindow::resetZoom);
}

/***************************************************************
* @function name:createHelpMenu()
* @摘要:创建帮助菜单
* @作用:为每个QAction设置状态栏提示、设置快捷键、绑定信号与槽等
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::createHelpMenu()
{
    QAction* viewHelpAction = new QAction(tr("查看帮助(H)"),this);
    helpMenu->addAction(viewHelpAction);
    viewHelpAction->setStatusTip(tr("跳转至微软帮助页面"));
    connect(viewHelpAction,&QAction::triggered,this,&MainWindow::helpManual);

    QAction* feedBackAction = new QAction(tr("发送反馈(F)"),this);
    helpMenu->addAction(feedBackAction);
    feedBackAction->setStatusTip(tr("该功能暂未考虑实现，后续也不准备实现"));

    helpMenu->addSeparator();

    QAction* aboutAction = new QAction(tr("关于"),this);
    helpMenu->addAction(aboutAction);
    aboutAction->setStatusTip(tr("查看作者版权等信息"));
    connect(aboutAction,&QAction::triggered,this,&MainWindow::about);


}

/***************************************************************
* @function name:createStatusBar()
* @摘要:创建状态栏
* @作用:包括显示光标对应的行列、缩放比例等
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::createStatusBar()
{
    ui->statusbar->setStyleSheet("QStatusBar {border:1px solid gray}");
    QStatusBar *statusBar = ui->statusbar;

    // 创建标签
    rowLabel = new QLabel("第 1 行，第 1 列", statusBar);
    zoom = new QLabel("100%", statusBar);
    curZoom = 100;
    QLabel *windowCRLF = new QLabel("Windows (CRLF)", statusBar);
    QLabel *encoding = new QLabel("UTF-8", statusBar);


    rowLabel->setStyleSheet("QLabel { border: 1px solid gray; }");
    zoom->setStyleSheet("QLabel { border: 1px solid gray; }");
    windowCRLF->setStyleSheet("QLabel { border: 1px solid gray; }");
    encoding->setStyleSheet("QLabel { border: 1px solid gray; }");

    statusBar->addPermanentWidget(rowLabel);
    statusBar->addPermanentWidget(zoom);
    statusBar->addPermanentWidget(windowCRLF);
    statusBar->addPermanentWidget(encoding);
}

/***************************************************************
* @function name:createNewFile()
* @摘要:新建txt文件槽函数的实现
* @作用:
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::createNewFile()
{
    QString text = textEdit->toPlainText();
    if(!text.isEmpty())
    {
        auto &dialog = GenericDialog::getInstance();
        dialog.setWinType(DialogType::ConfirmDialog)->setWinTitle("")
                ->setWinMessage(tr("是否要保存当前文本内容?"));
        dialog.exec();
        if(dialog.getSaveBtnClick())
        {
            //编辑保存的逻辑
            saveAsFile();
            textEdit->clear();
            currentFileName.clear();
            statusBar()->showMessage("文本已就绪");
            setWindowTitle(tr("HanL的记事本"));
        }else if(dialog.getNoSaveBtnClick())
        {
            textEdit->clear();
            currentFileName.clear();
            statusBar()->showMessage("文本已就绪");
        }
    }
}

/***************************************************************
* @function name:saveFile()
* @摘要: 保存txt文件槽函数的实现
* @作用:
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::saveFile()
{
    if(currentFileName.isEmpty())
    {
        qDebug()<<"saveFile file is null"<<__LINE__;
        saveAsFile();
    }else
    {
        save2File(currentFileName);
    }
}

/***************************************************************
* @function name:openFile()
* @摘要:打开.txt文件
* @作用:
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::openFile()
{
    //返回用户选择文件的路径
    QString filePath = QFileDialog::getOpenFileName(this,tr("打开文件"),"",
                                                    tr("文本文件 (*.txt);;所有文件(*)"));
    qDebug()<<"filePath:"<<filePath<<__LINE__;
    if(!filePath.isEmpty())
    {
        QFile file(filePath);
        if(!file.open(QFile::ReadOnly | QFile::Text))
        {
            auto &dialog = GenericDialog::getInstance();
            dialog.setWinType(DialogType::WarmingDialog)->setWinTitle(tr("HanL的记事本"))->
                    setWinMessage(tr("无法读取文件 %1:\n%2.").arg(QDir::toNativeSeparators(filePath)).arg(file.errorString()));

            dialog.exec();
        }
        QTextStream in(&file);
        in.setCodec("UTF-8");
        QApplication::setOverrideCursor(Qt::WaitCursor);
        textEdit->setPlainText(in.readAll());
        QApplication::restoreOverrideCursor();

        currentFileName = filePath;
        statusBar()->showMessage(tr("文件已加载"),2000);
        setWindowTitle(tr("%1 HanL的记事本").arg(QFileInfo(currentFileName).fileName()));
    }

}

/***************************************************************
* @function name:saveAsFile()
* @摘要:将文件另存为
* @作用:
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::saveAsFile()
{
    QString fileName = QFileDialog::getSaveFileName(this,tr("另存为"),"",tr("文本文件 (*.txt);;所有文件(*)"));//文本文件 (*.txt);;所有文件(*)
    if(!fileName.isEmpty())
    {
        if(!fileName.endsWith(".txt",Qt::CaseSensitive))
        {
            fileName += ".txt";
        }
        save2File(fileName);
    }
}

/***************************************************************
* @function name:openNewWin()
* @摘要:打开一个新窗口
* @作用:
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::openNewWin()
{
    QMainWindow* newWin = new MainWindow();
    newWin->show();
}

/***************************************************************
* @function name:closeApp()
* @摘要:退出该APP
* @作用:
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::closeApp()
{
    this->close();
}

void MainWindow::undo()
{
    textEdit->undo();
}

void MainWindow::cut()
{
    textEdit->cut();
}

void MainWindow::copy()
{
    textEdit->copy();
}

void MainWindow::paste()
{
    textEdit->paste();
}

/***************************************************************
* @function name:deleteSelect()
* @摘要: 删除选中文本
* @作用:
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::deleteSelect()
{
    if(textEdit->textCursor().hasSelection())
    {
        textEdit->textCursor().removeSelectedText();
    }
}

void MainWindow::allSelect()
{
    textEdit->selectAll();
}

/***************************************************************
* @function name:inputTimeAndDate()
* @摘要:获取当前时间和日期
* @作用:
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::inputTimeAndDate()
{
    QDateTime currTimeAndDate= QDateTime::currentDateTime();
    QString timeDateString =currTimeAndDate.toString("yyyy-MM-dd HH:mm:ss");

    textEdit->setPlainText(textEdit->toPlainText()+timeDateString);
    QTextCursor cursor = textEdit->textCursor();
    cursor.movePosition(QTextCursor::End);
    textEdit->setTextCursor(cursor);
}

/***************************************************************
* @function name:search()
* @摘要:查找对话框
* @作用:绑定查找的信号与槽
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::search()
{
    if(m_findDialog==nullptr)
    {
        m_findDialog = new FindTextDialog(this);
        // 计算居中位置
        m_findDialog->setGeometry(this->width()/2-300,this->height()/2-200,m_findDialog->width(),m_findDialog->height());
        connect(m_findDialog,&FindTextDialog::searchText,this,&MainWindow::searchMatchText);
    }
    m_findDialog->show();
}

/***************************************************************
* @function name:searchMatchText()
* @摘要: 查找匹配的字符串
* @作用: 找到后则高亮显示,否则通过对话框提示找不到输入的字符串
* @参数:
*      text:要查找的字符串
*      isCaseSensitive:是否区分大小写
*      isLoop:是否循环查找
*      direction:查找方向
* @返回值:void
**************************************************************/
void MainWindow::searchMatchText(const QString &text, bool isCaseSensitive, bool isLoop, bool direction)
{
    tempSearchStr = text;
    QTextDocument::FindFlags options;
    if(isCaseSensitive)
    {
        options |= QTextDocument::FindCaseSensitively;
    }
    if(!direction)
    {
        options |= QTextDocument::FindBackward;
    }
    //find函数默认在光标的位置开始查找,
    QTextCursor cursor = textEdit->textCursor();
    cursor.movePosition(QTextCursor::Start);
    textEdit->setTextCursor(cursor);

    bool foundRes = textEdit->find(text,options);

    if (!foundRes && isLoop)
    {
        // 回到文档开头（或结尾，取决于方向）重新查找
        if (options & QTextDocument::FindBackward)
        {
            // 向上查找失败 → 跳到文档末尾再找
            textEdit->moveCursor(QTextCursor::End);
        } else
        {
            // 向下查找失败 → 跳到文档开头再找
            textEdit->moveCursor(QTextCursor::Start);
        }
        foundRes = textEdit->find(text, options);
    }
    if(!foundRes)
    {
        isFound = false;
        QMessageBox::information(this,"HanL的记事本",(tr("找不到：%1")).arg(text),QMessageBox::Ok);
    }else
    {
        isFound = true;
        QPalette palette = textEdit->palette();
        palette.setColor(QPalette::Highlight,palette.color(QPalette::Active,QPalette::Highlight));
        textEdit->setPalette(palette);
    }
}


/***************************************************************
* @function name:replace()
* @摘要:替换对话框
* @作用:
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::replace()
{
    if(!m_replaceDialog)
    {
        m_replaceDialog = new ReplaceDialog(this);
        //m_replaceDialog->setGeometry(this->width()/2+210,this->height()/2+100,m_replaceDialog->width(),m_replaceDialog->height());
        connect(m_replaceDialog,&ReplaceDialog::searchNextText,this,&MainWindow::searchMatchText);
        connect(m_replaceDialog,&ReplaceDialog::replaceText,this,&MainWindow::replaceMatchText);
    }
    // 计算居中位置
    QPoint center = this->geometry().center();
    QSize dialogSize = m_replaceDialog->size();
    m_replaceDialog->move(center.x() - dialogSize.width() / 2,center.y() - dialogSize.height() / 2);

    m_replaceDialog->show();
}

/***************************************************************
* @function name:replaceMatchText()
* @摘要:替换匹配到的字符串
* @作用:
* @参数:
*      searchText:要查找的字符串
*      replaceText:要替换的字符串
*      isCaseSensitive:是否区分大小写
*      isLoop:是否循环查找
*      direction:查找方向
* @返回值:void
**************************************************************/
void MainWindow::replaceMatchText(const QString& searchText,const QString &replaceText, bool isCaseSensitive, bool isLoop, bool direction)
{
    searchMatchText(searchText,isCaseSensitive,isLoop,direction);
    if(!isFound) return;
    if(isFound)
    {
        QTextCursor cursor = textEdit->textCursor();
        if(!cursor.hasSelection())
        {
            QMessageBox::information(this, "提示", "没有选中的文本");
            return;
        }
        cursor.insertText(replaceText);
        textEdit->setTextCursor(cursor);
    }
}

/***************************************************************
* @function name: goToRow()
* @摘要:转到对应行窗口
* @作用:
* @参数:无
* @返回值:void
**************************************************************/
void MainWindow::goToRow()
{
    if(m_gotoRowDialog==nullptr)
    {
        m_gotoRowDialog = new GotoRowDialog(this);
        connect(m_gotoRowDialog,&GotoRowDialog::goToTargetRow,this,&MainWindow::goToTargetRow);;
    }
    // 计算居中位置
    QPoint center = this->geometry().center();
    QSize dialogSize = m_gotoRowDialog->size();
    m_gotoRowDialog->move(center.x() - dialogSize.width() / 2,center.y() - dialogSize.height() / 2);


    m_gotoRowDialog->show();
}

/***************************************************************
* @function name:goToTargetRow()
* @摘要:
* @作用:
* @参数:
*      targetRow:目标行数
* @返回值:void
**************************************************************/
void MainWindow::goToTargetRow(int targetRow)
{
    QTextCursor cursor =  textEdit->textCursor();
    int totalLine = textEdit->document()->blockCount();
    //cursor.blockNumber()+1 现在光标的位置对应的行号
    if(targetRow==1)
    {
        cursor.movePosition(QTextCursor::Start);
        textEdit->setTextCursor(cursor);
    }else if(cursor.blockNumber()+1 == targetRow)
    {
        cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
        textEdit->setTextCursor(cursor);
    }else if(targetRow>totalLine)
    {
        QMessageBox::information(this,"HanL的记事本-跳行","行数超过了总行数",QMessageBox::Ok);
        return;
    }else
    {
        QTextBlock block = textEdit->document()->findBlockByNumber(targetRow);
        textEdit->setTextCursor(QTextCursor(block));
    }
}

void MainWindow::updateActionEnable()
{
    bool isHasSelectText = textEdit->textCursor().hasSelection();
    cutAction->setEnabled(isHasSelectText);
    copyAction->setEnabled(isHasSelectText);
    deleteAction->setEnabled(isHasSelectText);
}

void MainWindow::updatePasteActionEnable()
{
    QClipboard *clipboard = QApplication::clipboard();
    bool isHasContent = !clipboard->text().isEmpty();
    pasteAction->setEnabled(isHasContent);
}

void MainWindow::checkInputTextEmpty()
{
    searchAction->setEnabled(!textEdit->toPlainText().trimmed().isEmpty());
    searchPreAction->setEnabled(!textEdit->toPlainText().trimmed().isEmpty());
    searchNextAction->setEnabled(!textEdit->toPlainText().trimmed().isEmpty());
    bingSearchAction->setEnabled(!textEdit->toPlainText().trimmed().isEmpty());
}

void MainWindow::isAutoWrap()
{
    if(autoWrapAction->isChecked())
    {
        textEdit->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
    }else
    {
        textEdit->setWordWrapMode(QTextOption::NoWrap);
    }
}

void MainWindow::selectFont()
{
    bool ok;
    QFont font = QFontDialog::getFont(&ok,textEdit->font(),this,"字体");
    if(ok)
    {
        textEdit->setFont(font);
    }
}

void MainWindow::zoomOut()
{
    if(curZoom<10)
    {
        curZoom = 10;
        zoom->setText(QString::number(curZoom)+"%");
        return;
    }
    zoom->setText(QString::number(curZoom-=10)+"%");

    textEdit->zoomOut();
}

void MainWindow::zoomIn()
{
    if(curZoom>=500)return;
    zoom->setText(QString::number(curZoom+=10)+"%");

    textEdit->zoomIn();
}

void MainWindow::resetZoom()
{
    while (curZoom>100)
    {
        textEdit->zoomOut();
        curZoom-=10;
    }
    while (curZoom<100)
    {
        textEdit->zoomIn();
        curZoom+=10;
    }
    curZoom = 100;
    zoom->setText("100%");
}

void MainWindow::statusBarShow()
{
    if(statusBar()->isVisible())
     {
        statusBar()->hide();
    }else
    {
        statusBar()->show();
    }
}

void MainWindow::updateCursorPos()
{
    QTextCursor cursor = textEdit->textCursor();

    int row = cursor.blockNumber()+1;
    int col = cursor.columnNumber()+1;
    //第 1 行，第 1 列
    rowLabel->setText("第 "+QString::number(row)+" 行，第 "+QString::number(col)+" 列");
}

void MainWindow::about()
{
    if(m_aboutDialog==nullptr)
    {
        m_aboutDialog = std::make_unique<AboutDialog>(this);
        m_aboutDialog->setGeometry(this->width()/2-270,this->height()/2-270,m_aboutDialog->width(),m_aboutDialog->height());
    }
    m_aboutDialog->show();
}


void MainWindow::helpManual()
{
    bool isOpen = QDesktopServices::openUrl(QUrl(QString("https://support.microsoft.com/zh-cn/article/711b6492-0435-0038-8706-7c6b0feb200a")));
    if(isOpen)
    {
        LOG(ERROR) <<"MainWindow::helpManual()]  help Manual open failed;";
    }else
    {
        LOG(ERROR) <<"帮助文档打开失败"<<__LINE__;
    }
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    auto &dialog = GenericDialog::getInstance();
    if(textEdit->toPlainText().isEmpty())
    {
        dialog.setWinTitle("");
        dialog.setWinType(DialogType::TipDialog);
        dialog.setWinMessage("您确定要关闭窗口吗？");
    }else
    {
        dialog.setWinTitle("");
        dialog.setWinType(DialogType::ConfirmDialog);
        dialog.setWinMessage("您是否需保存文档内容？");

    }
    dialog.showDialog();
    if(dialog.getNoSaveBtnClick())
    {
        this->close();
    }else if(dialog.getCancelBtnClick())
    {
        event->ignore();
    }else
    {
       saveFile();
       event->ignore();
    }
}

bool MainWindow::isSaveCurText()
{
    if(textEdit->document()->isModified())
    {
        auto &dialog = GenericDialog::getInstance();
        dialog.setWinTitle(tr("HanL的记事本"))->setWinMessage("文件已修改，是否保存?")->setWinType(DialogType::ConfirmDialog);
        dialog.exec();
        if(dialog.getSaveBtnClick())
        {
            return save2File(currentFileName);
        }else
        {
            return false;
        }
    }
    return true;
}

bool MainWindow::save2File(const QString &fileName)
{
    QFile file(fileName);
    if(!file.open(QFile::WriteOnly | QFile::Text))
    {
        auto &dialog = GenericDialog::getInstance();
        dialog.setWinTitle(tr("HanL的记事本"))->setWinMessage(tr("无法写入文件 %1:\n%2.").
                                                          arg(QDir::toNativeSeparators(fileName)).
                                                          arg(file.errorString()))->setWinType(DialogType::TipDialog);
        dialog.exec();
        return false;
    }
    QTextStream out(&file);
    QApplication::setOverrideCursor(Qt::WaitCursor);
    out<<textEdit->toPlainText();
    QApplication::restoreOverrideCursor();

    currentFileName = fileName;
    statusBar()->showMessage(tr("文件已经保存"));
    textEdit->document()->setModified(false);
    setWindowTitle(tr("%1 - HanL的记事本").arg(QFileInfo(currentFileName).fileName()));
    return true;
}



